home *** CD-ROM | disk | FTP | other *** search
- ; Assembler interface to Turbo Pascal - CPU
- ;
- ; Copyright 1989 by Mark R. Boler - All Rights Reserved
-
- TITLE CPU
-
- POPFF macro
- local L1, L2
-
- jmp short L2
- L1:
- iret
-
- L2:
- push cs
- call L1
-
- endm
-
- CODE SEGMENT WORD PUBLIC
-
- ASSUME CS:CODE
-
- PUBLIC CpuInfo
-
- ; FUNCTION CpuInfo: WORD; EXTERNAL;
-
- ARG_STR STRUC
-
- dw ?
- ARG_OFF dw ?
- ARG_SEG dw ?
- ARG_FLG dw ?
-
- ARG_STR ENDS
-
- FLG_08 EQU 000000000B
- FLG_06 EQU 000000001B
- FLG_NEC EQU 000000010B
- FLG_18 EQU 000000100B
- FLG_28 EQU 000000111B
- FLG_38 EQU 000001001B
- FLG_87 EQU 000010000B
- FLG_287 EQU 000100000B
- FLG_387 EQU 000110000B
- FLG_1167 EQU 010000000B
- FLG_BAD EQU 100000000B
-
- CpuInfo PROC FAR
- mov ah, 01110000B ; set up ah for flags
- push ax ; put them into the flags
- popf
- pushf ; get them back into ah for testing
- pop ax
- test ah, 10000000B ; if flags bit 15 set = 8088/86/188/186
- jnz SHORT LowCPU ; jump if it is an 8088/86 or 80188/186
- test ah, 01110000B ; if bits 12-14 set it is an 80286
- jnz SHORT Is386 ; jump if it is an 80386
- mov bx, FLG_28 ; set to 80286 processor
- jmp SHORT CkMathCPU ; check for math cpu
- Is386:
- mov bx, FLG_38 ; set to 80386 processor
- jmp SHORT CkMathCPU ; check for math cpu
- LowCPU: ; determine which 801x processor
- mov al, 11111111B ; set al to all 1's
- mov cl, 33 ; and 8088/86 will do a 33 bit shift
- shl ax, cl ; an 80188/186 will only shift 1 time
- jnz SHORT Is18x ; jump if it is an 80188/80186
- mov bx, FLG_NEC ; assume NEC processor
- call CkNEC ; see if it is NEC processor
- jcxz CkPFQ ; it was so check pre-fetch queue
- mov bx, FLG_08 ; it is an 808x processor
- jmp SHORT CkPFQ ; check pre-fetch queue
- Is18x:
- mov bx, FLG_18 ; set to 8018x processor
-
- CkPFQ:
- xor dx, dx ; set up max holding variable in dx
- mov cx, 8 ; set up count variable in cx
- CkPFQ1:
- call PFQSub ; check the value
- cmp ax, dx ; use the larger of the two
- jbe CkPFQ2 ; ax is smaller
- mov dx, ax ; save for later in dx
- CkPFQ2:
- loop CkPFQ1 ; loop until all iterations done
- cmp dx, 4 ; Check PFQ
- jbe CkBadChip ; Jump if xxxx8
- or bx, FLG_06 ; PFQ length is 5 or longer
-
- CkBadChip:
- call CkChip ; call subroutine
- jcxz CkMathCPU ; if cx is 0 then the CPU is good
- or bx, FLG_BAD ; it is a bad chip
- CkMathCPU:
- call MathCPU ; call subroutine
- mov ax, bx ; set return value into ax
- ret ; return to caller
- CpuInfo ENDP
-
- CkNEC PROC NEAR
- mov cx, 0FFFFh ; read max amount of bytes
- sti ; make sure we are interrupted at least once
- rep lods BYTE PTR es:[si] ; es and direction flag doesn't matter
- ret ; if cx = 0 then NEC, else Intel CPU
- CkNEC ENDP
-
- PFQSub PROC NEAR
-
- ASSUME ds:CODE, es:CODE
-
- @REP EQU 18 ; max length of PFQ we can handle
-
- push bx ; save bx
- push cx ; save cx
- push dx ; save dx
- std ; string ops go backwards
- mov cx, @REP ; Loop counter
- mov ax, cs ; make es:[di] = PFQ last byte in fill area
- mov es, ax
- lea di, LAB_NOP + @REP - 1
- mov al, cs:LAB_INC ; Change to inc bx
- mov ah, cs:LAB_NOP
- mov si, 1
- xor dx, dx
- cli
-
- EVEN
- nop
- PFQSub_NEXT:
- xor bx, bx ; Initialize flag
- div si
- stosb ; Change the instruction
-
- LAB_NOP label byte
- rept @REP
- nop ;; Fill byte
- endm
- mov es:[di + 1], ah ; Restore the NOP
- or bx, bx
- loopnz PFQSub_NEXT
- sti
- mov ax, cx
- inc ax
- pop dx
- pop cx
- pop bx ; get bx back
- ret ; return to caller
-
- LAB_INC label byte
- inc bx ; increment flag
- PFQSub ENDP
-
- CkChip PROC NEAR
- ASSUME ds:CODE, es:CODE
-
- push bx ; save bx
- push ds ; save ds
- mov ax, 35H * 256 + 1 ; get interrupt vector 1 function
- int 21H ; call DOS
- push es
- push bx
- mov dx, OFFSET INT01
- mov ax, cs
- mov ds, ax
- mov ax, 25H * 256 + 1 ; set interrupt vector 1 function
- int 21H ; call DOS
- cli ; turn off interrupts
- mov cx, 1 ; initialize a register
- push ss
- pushf
- pop ax
- or ax, 100000000B
- push ax
- POPFF
-
-
- nop
- POST_NOP:
- pop ss
- dec cx
-
-
- hlt
- INT01:
-
- push bp
- mov bp, sp
-
- cmp [bp].ARG_OFF, OFFSET cs:POST_NOP ; check offset
- pop bp ; restore bp
- ja INT01_DONE
-
- iret ; return to caller
- INT01_DONE:
-
- ; Restore old INT 01h handler
-
- pop dx ; get old offset
- pop ds ; get old segment
- mov ax, 25H * 256 + 1 ; set interrupt vector 1 function
- int 21H ; call DOS
- sti ; Allow interrupts again
- add sp, 3 * 2 ; Strip IP, CS, and Flags from stack
- pop ds ; restore ds
- pop bx ; restore bx
- ret ; return to caller
- CkChip ENDP
-
- Control EQU WORD PTR [bp - 2] ; control word in local stack storage
- ControlL EQU BYTE PTR [bp - 2] ; low byte of control word
- ControlH EQU BYTE PTR [bp - 1] ; high byte of control word
-
- MathCPU PROC NEAR
- push bp ; save bp
- mov bp, sp ; set up stack frame
- xor ax, ax ; set up and init local data
- FNINIT
- push ax
- FNSTCW Control
- cmp ControlH, 03H
- jne SHORT MDone
- mov al, 87
- and ControlL, 01111111B
- FLDCW Control
- FDISI
- FSTCW Control
- test ControlL, 10000000B
- je SHORT Not87
- or bx, FLG_87
- jmp SHORT MDone
- Not87:
- FINIT
- FLD1
- FLDZ
- FDIV
- FLD ST
- FCHS
- FCOMPP
- FSTSW Control
- FWAIT
- mov ah, ControlH
- SAHF
- or bx, FLG_387
- jne SHORT MDone
- or bx, FLG_287
- MDone:
- mov sp, bp
- pop bp
- ret ; return to caller
- MathCPU ENDP
-
- CkWeitek PROC NEAR
-
- ASSUME ds:CODE, es:CODE
- test bx, FLG_38 ; Are we on a 38x?
- jz CkWeitek_EXIT ; No, thus no 1167
- db 66h ; Use EAX
- push ax ; Save for a moment
- db 66h ; Use EAX
- xor ax, ax ; Clear entire register
- int 11h ; Get equipment flags
- db 66h ; Use EAX
- test ax, 0000h
- dw 0100h ; Test bit 24
- jz CkWeitek_EXIT0 ; Not present
- or bx, FLG_1167 ; Mark as present
- CkWeitek_EXIT0:
- db 66h ; Use EAX
- pop ax ; Restore
- CkWeitek_EXIT:
- ret ; Return to caller
- CkWeitek ENDP
-
- CODE ENDS
-
- END